package com.jsl.action;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class AddProjectClassLoader extends ClassLoader{
    private static final Logger log = LoggerFactory.getLogger(AddProjectClassLoader.class);
    // 类文件所在目录
    private String classPath;

    public AddProjectClassLoader(String classPath) {
        // 明确指定父类加载器为系统类加载器
        super(Thread.currentThread().getContextClassLoader());
        log.info("当前类加载器：{}",Thread.currentThread().getContextClassLoader());
        this.classPath = classPath;
    }

    /**
     * 重写loadClass，绕过双亲委派机制
     * 只加载指定包的类，其他类仍委托给系统类加载器
     */
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        // 只有热更新包下的类自己加载，其他委托给父加载器
        if (name.startsWith("hotswap.project.")) {
            synchronized (getClassLoadingLock(name)) {
                // 先检查是否已加载
                Class<?> c = findLoadedClass(name);
                if (c != null) {
                    return c;
                }
                return findClass(name);
            }
        }
        try {
            // 其他类（如接口类）委托给系统类加载器
            return super.loadClass(name);
        } catch (ClassNotFoundException e) {
            log.error("父加载器无法加载类: {}, 错误: {}", name, e.getMessage());
            throw e; // 重新抛出，不要让系统回退到findClass
        }
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            // 读取类文件字节
            byte[] classData = loadClassData(name);
            if (classData == null) {
                log.error("无法找到该类: " + name);
                throw new ClassNotFoundException();
            }
            // 将字节数组转换为Class对象
            return defineClass(name, classData, 0, classData.length);
        } catch (IOException e) {
            log.error("Failed to load class: " + e.getMessage());
            throw new ClassNotFoundException(name, e);
        }
    }

    // 从文件加载类的字节码
    private byte[] loadClassData(String className) throws IOException {
        String path = classPath + File.separatorChar +
                className.replace('.', File.separatorChar) + ".class";
        File file = new File(path);
        if (!file.exists()) {
            return null;
        }

        try (FileInputStream fis = new FileInputStream(file);
             ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[4096];
            int length;
            while ((length = fis.read(buffer)) != -1) {
                bos.write(buffer, 0, length);
            }
            return bos.toByteArray();
        }
    }
}
